/******************************************************************************

  File Name     : mp_common.h
  Version       : Initial Draft
  Author        : tongzhilin
  Created       : 2020/8/6
  Last Modified :
  Description   : mp_common
  Function List :
  History       :
  1.Date        : 2020/8/6
    Author      : tongzhilin
    Modification: Created file

******************************************************************************/
#pragma once
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#include <stddef.h>
#include <malloc.h>
#include <time.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>
#include <stdint.h>

#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#ifdef __cplusplus
#include <vector>
#include <map>
#include <memory>
#include <algorithm> 
#include <chrono>
#include <cmath>
#include <thread>
#include <mutex>
#include <unordered_map>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <fstream> 
#include <cstddef>
#include <sstream>
#include <string>
#include <iterator>
#include <exception>
#include <stdexcept>
#include <sys/syscall.h>    //syscall
#endif
#include "mp_types.h"

#define NONE    "\033[0m" 
#define GREEN   "\033[0;32m"
#define RED     "\033[;31m"
#define YELLOW  "\033[;33m"
#define NORMAL  "\033[0;39m"
#define BLUE    "\033[1;34m"
#define MAGENTA "\033[1;35m"
#define CYAN    "\033[1;36m"
#define WHITE   "\033[1;37m"

#define MP_LOG_DBG_OPEN    1
#define MP_LOG_INFO_OPEN   1
#define MP_LOG_ERR_OPEN    1
#define MP_LOG_FATAL_OPEN  1

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

INT32 mp_sleep_us(UINT32 us);
INT32 mp_sleep_ms(UINT32 ms);
INT32 mp_sleep_s(UINT32 s);
void  mp_printf(const char *fmt, ...);

UINT64 mp_getmillisecond(void);
UINT64 mp_getrelativems(VOID);

#ifdef __cplusplus
}
#endif  /* __cplusplus */

#ifndef MP_MIN
#  define MP_MIN(a,b)  ((a) > (b) ? (b) : (a))
#endif

#ifndef MP_MAX
#  define MP_MAX(a,b)  ((a) < (b) ? (b) : (a))
#endif

#define MP_LOG_DBG(fmt, ...)          \
do                                                              \
{\
    if(MP_LOG_DBG_OPEN)  \
    {  \
        mp_printf("[DEBUG][%lu]%s:%s(%d): " fmt, syscall(SYS_gettid), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
    }  \
}\
while (0)

#define MP_LOG_INFO(fmt, ...)          \
do                                                              \
{\
    if(MP_LOG_INFO_OPEN)  \
    {  \
        mp_printf("[INFO][%lu]%s:%s(%d): " fmt, syscall(SYS_gettid), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
    }  \
}\
while (0)

#define MP_LOG_ERR(fmt, ...)          \
do                                                              \
{\
    if(MP_LOG_ERR_OPEN)  \
    {  \
        mp_printf("[ERROR][%lu]%s:%s(%d): " RED fmt NONE, syscall(SYS_gettid), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
    }  \
}\
while (0)

#define MP_LOG_FATAL(fmt, ...)          \
do                                                              \
{\
    if(MP_LOG_FATAL_OPEN)  \
    {  \
        mp_printf("[FATAL][%lu]%s:%s(%d): " MAGENTA fmt NONE, syscall(SYS_gettid), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
        mp_sleep_s(1);\
        *((UCHAR*)0x00) = 0x00;\
    }  \
}\
while (0)

#define MP_ASSERT(x) do \
{ \
    if (!(x)) \
    { \
        MP_LOG_FATAL("Assert error at %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);  \
    } \
} while (0)

#define MP_CHECK(x) do \
{ \
    auto _ret = (x); \
    if (_ret != 0) \
    { \
        MP_LOG_ERR("Error at %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); \
        MP_LOG_FATAL("Error code is (%x)\n", _ret); \
    }\
} while (0)

#define CHECK_NON_NULL_POINTER(ptr, rtn) do \
{ \
    if (ptr == NULL) \
    { \
        MP_LOG_ERR("Param is NULL " #ptr ", error\n"); \
        return rtn; \
    } \
} while (0)
#define CHECK_INT_OVERFLOW(para, start, end, rtn) do \
{ \
    if (para < start || para > end) \
    { \
        MP_LOG_ERR("Param is overflow " #para ", error\n"); \
        return rtn; \
    } \
}while(0)

#define TIME_START(time) time = mp_getrelativems();
#define TIME_END(time_start, flag, ...) do \
{ \
    MP_LOG_INFO(flag"%lld ms \n", ##__VA_ARGS__, (mp_getrelativems() - time_start)); \
}while(0)

